#pragma once
#include "./mq_binding.hpp"
#include "./mq_exchange.hpp"
#include "./mq_message.hpp"
#include "./mq_queue.hpp"

namespace mq_zxws
{
    class VirtualHost
    {
    public:
        using ptr = std::shared_ptr<VirtualHost>;
        VirtualHost(const std::string & name, const std::string & basedir, const std::string & dbfile)
            :_host_name(name)
            ,_bmp(std::make_shared<BindingManager>(dbfile))
            ,_emp(std::make_shared<ExchangeManager>(dbfile))
            ,_mqmp(std::make_shared<MsgQueueManager>(dbfile))
            ,_mmp(std::make_shared<MessageManager>(basedir))
        {
            QueueMap qmap = _mqmp->AllQueues();
            for(auto& it:qmap){
                _mmp->initQueueMessage(it.first);
            }
        }

        bool declareQueue(const std::string& name,
                bool durable,
                bool exclusive,
                bool auto_delete,
                const google::protobuf::Map<std::string, std::string>& args){
            _mmp->initQueueMessage(name);
            return _mqmp->declareQueue(name, durable, exclusive, auto_delete, args);
        }
        void deleteQueue(const std::string& name){
            _bmp->removeMsgqueueBindings(name);
            _mqmp->deleteQueue(name);
            _mmp->destoryQueueMessage(name);
        }
        bool existsQueue(const std::string & qname){
            return _mqmp->exists(qname);
        }

        bool declareExchange(const std::string& ename,
                ExchangeType type,
                bool durable,
                bool auto_delete,
                const google::protobuf::Map<std::string, std::string>& args){
            return _emp->declareExchange(ename, type, durable, auto_delete, args);
        }
        void deleteExchange(const std::string& ename){
            _bmp->removeExchangeBindings(ename);
            _emp->deleteExchange(ename);
        }
        bool existsExchange(const std::string& ename){
            return _emp->exists(ename);
        }
        Exchange::ptr selectExchange(const std::string& ename){
            return _emp->selectOne(ename);
        }

        bool bind(const std::string& ename, const std::string & qname, const std::string & key){
            auto ep = _emp->selectOne(ename);
            if(ep.get() == nullptr){
                DLOG("进行队列绑定失败，交换机 %s 不存在", ename.c_str());
                return false;
            }
            auto qp = _mqmp->selectOne(qname);
            if(qp.get() == nullptr){
                DLOG("进行队列绑定失败，队列 %s 不存在", qname.c_str());
                return false;
            }
            return _bmp->Bind(ename, qname, key, ep->durable && qp->durable);
        }
        void unBind(const std::string& ename, const std::string & qname){
            _bmp->unBind(ename, qname);
        }
        MsgQueueBindingMap getExchangeBindings(const std::string& ename){
            return _bmp->getExchangeBindings(ename);
        }
        bool existsBinding(const std::string& ename, const std::string& qname){
            return _bmp->exists(ename, qname);
        }


        bool basicPublish(const std::string& qname, const BasicProperties * bp, std::string body){
            auto qp = _mqmp->selectOne(qname);
            if(qp.get() == nullptr){
                DLOG("进行队列绑定失败，队列 %s 不存在", qname.c_str());
                return false;
            }
            return _mmp->insert(qname, bp, body, qp->durable);
        }
        void basicAck(const std::string& qname, const std::string & id){
            _mmp->ack(qname, id);
        }
        MessagePtr basicConsume(const std::string& qname){
            return _mmp->front(qname);
        }
        QueueMap AllQueues(){
            return _mqmp->AllQueues();
        }

        void clear(){
            _bmp->clear();
            _emp->clear();
            _mqmp->clear();
            _mmp->clear();
        }
    private:
        std::string _host_name;
        BindingManager::ptr _bmp;   // 绑定信息句柄
        ExchangeManager::ptr _emp;  // 交换机管理句柄
        MsgQueueManager::ptr _mqmp; // 队列管理句柄
        MessageManager::ptr _mmp;   // 队列消息管理句柄
    };
}